/*
 *  joint.h
 *  EPPI-0.0
 *
 *  Created by Juan Carlos Garcia Orden on 22/01/09.
 *
 */
 
#ifndef _joint_h_
#define _joint_h_

#include <iostream>
#include <fstream>
#include <vector>
#include <map>
#include <algorithm>
#include <string>
#include "point.h"
#include "CONSTRAINTS/constraint.h"
#include "BODIES/body.h"

using namespace std;

class MecSystem;
class Constraint;

class Joint
{
public:
	string name;
	int dim;								/** Space dimension */
	MecSystem* parentSystem;				/** Parent system */
	string outGraphFilex;
	vector<string> vPointNamesSurface;	 // Names of the nodes on the surface (without /systemName)
	vector<Point*> vPPointSurface;		// Pointers to surface points
	ofstream localFGraph;
	string bodyName1;
	string bodyName2;
	Body* PBody1;
	Body* PBody2;
	double cstiffness;
	double cdamping;
	double cfriction;
	vector<Constraint*> vConstraints;			/** Vector of constraints */
	
public:	
	Joint();
	Joint(ifstream &, string, MecSystem*);
	virtual ~Joint(){}
	
	void setDofs();							/** Set degrees of freedom from its components */
	void setLocalGlob();					/** Set local-global numbering on components */
	void setLoad(string, ifstream &, const vector<double> &, const map<string,vector<string>,less<string> >*);		/** Set concentrated load */
	void reportLoads();
	void reportContent();
	void initializeGlobalDofs(vector<double> &, vector<double> &, const double& time);
	void fillResidual(vector<double>& res_in,
					  vector<double>& q_in,
  					  vector<double>& dq_in,
					  const double& time, const int&, const double&, const int&, const double&);

	void fillResidual(vector<double>& residue,
					  const vector<double>& q,
					  const vector<double>& qdot,
					  const vector<double>& qddot,
					  const double& time,
					  const int&,
					  const double&, const int&,
  					  const int&,
					  const double&
					  );	
	void fillResFi(	vector<double>& residue,
				   const vector<double>& q,
				   const vector<double>& qddot,
				   const int&
				   );
	void fillResFq(	vector<double>& residue,
				   const vector<double>& q,
				   const vector<double>& qdot,
				   const int&,
   				   const int&,
				   const double&
				   );
	void fillResFt(	vector<double>& residue,
				   const double& time,
				   const int&,
				   const double&, const int&
				   );
	
	void fillTangent(sparseMatrix&, vector<vector<double> >&, vector<vector<double> >&, vector<vector<double> >&, 
					 vector<int>&, vector<int>&, 
					 vector<double>&, vector<double>&,
					 const double& time, const int&);

	void fillTangent(sparseMatrix&, vector<vector<double> >&, vector<vector<double> >&, vector<vector<double> >&,
					 vector<int>&, vector<int>&,
					 const vector<double>& q,
					 const vector<double>& qdot,
					 const vector<double>& qddot,
					 double partial_qdot,
					 double partial_qddot,
					 const double& time,
					 const int&,
 					 const int&,
					 const double&
					 );
	
	void fillMassMatrix(sparseMatrix& Ma, const vector<double>& q, const double& time );

	void fillMassMatrix(vector<double>& vMa, const vector<double>& q, const double& time );
	
	void fillForce(		vector<double>& f,
				   const vector<double>& q,
				   const vector<double>& qdot,
				   const double& time,
				   const double&, const int&
				   );
	
	void setSparsePattern(vector< vector<int> >&);
	void setSparsePatternInertia(vector< vector<int> >&);
	void changePointName(string&, string&);

    void writeFileGraph(ofstream&,string&,string&,string&);	/** Write graphical output to file */
	void initializeCompRes(const bool&, const double&, const int&, const bool);
	void initializeCompTang(const bool&);
	void calcEner(double&, double&, double&, double&, double&, double&, double&, int&, vector<double>&, vector<double>&);
	void calcEntropy(double&, double&);
	void calcAM(vector<double>&, vector<double>&, vector<double>&);
	void calcCon(vector<double> &, vector<double>&, vector<double>&, vector<double>&, double&);
	void update(const int&, const vector<double>&, const vector<double>&);
	void setInitialConditions(vector<double>&, vector<double>&);
	void setTemperature(double&);
	void setTRNumbers(int&);
	void updateDofs(vector<double>&, vector<double>&);
	int setInertiaNumbers(int, vector<int>&);
	void setQatComponents(const vector<double>&, const vector<double>&);
	void updateLagMul(void);
	void checkConvLagMul(bool&);
	void calcProjMatrix(sparseMatrix&, double&);
	void fillPhiq(vector<vector<double> >&, int&);
	
	/** Virtual functions */
	virtual void setPTPointsCons()=0;		/** Set pointers to points in each constraint */
	virtual void setPPointSurface()=0;		/** Set pointers to surface points in each component */
	virtual void writeMSH(ofstream&)=0;		/** MSH format for Gmsh */
	virtual void writeVTU(ofstream&)=0;		/** VTU format for Paraview */
	virtual void writeOOGL(ofstream&)=0;	/** OOGL format for Geomview */
	virtual void createContacts(){};
	virtual void setParamAtCons(){};
	
	/** Friend functions */
	friend void addSystemName(string& str, const string& strname);
	friend string getStringHead(const string& str);
	friend string getStringTail(const string& str);
	friend 	bool checkForSlash(const string& str);
};
#endif
